Le mapping correspond au schéma des tables en SQL classique.
Pour récupérer le mapping d'un type
$ curl -X GET :9200/index/type/_mapping
Utiliser un mapping explicite permet d'avoir de meilleure perf en insert. Ca permet également de
Exemple de mapping
"orders" : {
"properties" : {
"id": {
"type": "string",
"store": "yes",
"index": "not_analyzed"
}
}
Lorsqu'on crée un mapping, on peut également donner à elastic des hints sur la méthode pour mieux gérer les champs.
On a également la possibilité de pouvoir utiliser un template dynamique pour le mapping des documents.
La manière dont l'index se crée dépend, du type d'analyzeur choisit pendant le mapping.
Admettons qu'on veuille indexer cette phrase :
Peter's house is big.
Type d'analyzer au mapping | Analyzer | Tokens |
---|---|---|
Pas de mapping | Pas d'index | Pas de token |
not_alanyzed | KeywordAnalyzer | [Peter's house is big] |
analyzed | StandardAnalyzer | ["peter", "s", "house", "is", "big"] |
On constate donc que le,
peter
mais pas Peter
. Structurer correctement les données peut permettre des gains de perf assez conséquent.
A la base tout les champs contenu dans un objet sont vu comme un seul et même objet et il n'est pas possible de distinguer les valeurs entre différent objet encapsulés dans un même tableau.
Heureusement elastic nous permet graĉe à un attribut de faire cette distinction :
Exemple :
"orders" : {
"properties" : {
"id": {
"type": "string",
"store": "yes",
"index": "not_analyzed"
},
"test" : {
"type": "nested",
"properties" : {
"name:" : { "type": "string", "store":"no" }
}
}
}
}
D'une manière assez simple si un document est marqué comme "nested", il va être extrait du document original et indexé comme un document externe. Les nested object ne peuvent pas être recherché à l'aide de query classique, uniquement avec des nested query.
Pour définir un point géographique rien de plus simple :
"orders" : {
"properties" : {
"customer_location": {
"type": "geo_point",
"store": "yes"
}
}
$ curl -XPUT 'http://localhost:9200/twitter/_mapping/tweet' -d '
{
"tweet" : {
"properties" : {
"message" : {"type" : "string", "store" : true }
}
}
}'
Configurer un analyseur particulier en français :
"settings": {
"analysis": {
"filter": {
"elision": {
"type": "elision",
"articles": ["l", "m", "t", "qu", "n", "s", "j", "d"]
}
},
"analyzer": {
"custom_french_analyzer": {
"tokenizer": "letter",
"filter": ["asciifolding", "lowercase", "french_stem", "elision", "stop"]
},
"tag_analyzer": {
"tokenizer": "keyword",
"filter": ["asciifolding", "lowercase"]
},
}
}
},
Analyseur francais relativement complet :
{
"settings": {
"analysis": {
"filter": {
"french_elision": {
"type": "elision",
"articles": [ "l", "m", "t", "qu", "n", "s",
"j", "d", "c", "jusqu", "quoiqu",
"lorsqu", "puisqu"
]
},
"french_stop": {
"type": "stop",
# Peut être remplacé par "_french_"
"stopword" : ["ès", "vers", "a", "à", "afin", "ai", "ainsi", "après", "attendu", "au", "aujourd", "auquel", "aussi", "autre", "autres", "aux", "auxquelles", "auxquels", "avait", "avant", "avec", "avoir", "c", "ça", "car", "ce", "ceci", "cela", "celle", "celles", "celui", "cependant", "certain", "certaine", "certaines", "certains", "ces", "cet", "cette", "ceux", "chez", "ci", "combien", "comme", "comment", "concernant", "contre", "d", "dans", "de", "debout", "dedans", "dehors", "delà", "depuis", "derrière", "des", "dès", "désormais", "desquelles", "desquels", "dessous", "dessus", "devant", "devers", "devra", "divers", "diverse", "diverses", "doit", "donc", "dont", "du", "duquel", "durant", "elle", "elles", "en", "entre", "environ", "est", "et", "etc", "été", "etre", "être", "eu", "eux", "excepté", "hélas", "hormis", "hors", "hui", "il", "ils", "j", "je", "jusqu", "jusque", "l", "la", "là", "laquelle", "le", "lequel", "les", "lesquelles", "lesquels", "leur", "leurs", "lorsque", "lui", "ma", "mais", "malgré", "me", "même", "mêmes", "merci", "mes", "mien", "mienne", "miennes", "miens", "moi", "moins", "mon", "moyennant", "n", "ne", "néanmoins", "ni", "non", "nos", "notre", "nôtre", "nôtres", "nous", "ô", "on", "ont", "ou", "où", "outre", "par", "parmi", "partant", "pas", "passé", "pendant", "plein", "plus", "plusieurs", "pour", "pourquoi", "près", "proche", "puisque", "qu", "quand", "que", "quel", "quelle", "quelles", "quels", "qui", "quoi", "quoique", "revoici", "revoilà", "s", "sa", "sauf", "se", "selon", "seront", "ses", "si", "sien", "sienne", "siennes", "siens", "sinon", "soi", "soit", "son", "sont", "sous", "suivant", "sur", "ta", "te", "tes", "tien", "tienne", "tiennes", "tiens", "toi", "ton", "tous", "tout", "toute", "toutes", "tu", "un", "une", "va", "voici", "voilà", "vos", "votre", "vôtre", "vôtres", "vous", "vu", "y"]
},
# Les mots qui vont être exclu du stemmer, à remove si on veut pas en exclure
"french_keywords": {
"type": "keyword_marker",
"keywords": []
},
"french_stemmer": {
"type": "stemmer",
"language": "light_french"
}
},
"analyzer": {
"french": {
"tokenizer": "standard",
"filter": [
"french_elision",
"lowercase",
"french_stop",
"french_keywords",
"french_stemmer"
]
}
}
}
}
}
Possibilité de directement le setup depuis le JSON ou via un fichier txt.
PUT /my_index
{
"settings": {
"analysis": {
"filter": {
"my_synonym_filter": {
"type": "synonym",
"synonyms": [
"british,english",
"queen,monarch"
]
}
},
"analyzer": {
"my_synonyms": {
"tokenizer": "standard",
"filter": [
"lowercase",
"my_synonym_filter"
]
}
}
}
}
}
A l'aide d'un fichier texte reprenant le Solr synonym system file :
# blank lines and lines starting with pound are comments.
#Explicit mappings match any token sequence on the LHS of "=>"
#and replace with all alternatives on the RHS. These types of mappings
#ignore the expand parameter in the schema.
#Examples:
i-pod, i pod => ipod,
sea biscuit, sea biscit => seabiscuit
#Equivalent synonyms may be separated with commas and give
#no explicit mapping. In this case the mapping behavior will
#be taken from the expand parameter in the schema. This allows
#the same synonym file to be used in different synonym handling strategies.
#Examples:
ipod, i-pod, i pod
foozball , foosball
universe , cosmos
# If expand==true, "ipod, i-pod, i pod" is equivalent
# to the explicit mapping:
ipod, i-pod, i pod => ipod, i-pod, i pod
# If expand==false, "ipod, i-pod, i pod" is equivalent
# to the explicit mapping:
ipod, i-pod, i pod => ipod
#multiple synonym mapping entries are merged.
foo => foo bar
foo => baz
#is equivalent to
foo => foo bar, baz
En utilisant le mapping suivant :
{
"index" : {
"analysis" : {
"analyzer" : {
"synonym" : {
"tokenizer" : "whitespace",
"filter" : ["synonym"]
}
},
"filter" : {
"synonym" : {
"type" : "synonym",
"synonyms_path" : "analysis/synonym.txt"
}
}
}
}
}
$ curl -XPUT localhost:9200/geoloc -d '{
"settings": {
"index": {
"analysis": {
"filter": {
"french_elision": {
"type": "elision",
"articles": [ "l", "m", "t", "qu", "n", "s",
"j", "d", "c", "jusqu", "quoiqu",
"lorsqu", "puisqu"
]
},
"french_stop": {
"type": "stop",
"stopword" : ["ès", "vers", "a", "à", "afin", "ai", "ainsi", "après", "attendu", "au", "aujourd", "auquel", "aussi", "autre", "autres", "aux", "auxquelles", "auxquels", "avait", "avant", "avec", "avoir", "c", "ça", "car", "ce", "ceci", "cela", "celle", "celles", "celui", "cependant", "certain", "certaine", "certaines", "certains", "ces", "cet", "cette", "ceux", "chez", "ci", "combien", "comme", "comment", "concernant", "contre", "d", "dans", "de", "debout", "dedans", "dehors", "delà", "depuis", "derrière", "des", "dès", "désormais", "desquelles", "desquels", "dessous", "dessus", "devant", "devers", "devra", "divers", "diverse", "diverses", "doit", "donc", "dont", "du", "duquel", "durant", "elle", "elles", "en", "entre", "environ", "est", "et", "etc", "été", "etre", "être", "eu", "eux", "excepté", "hélas", "hormis", "hors", "hui", "il", "ils", "j", "je", "jusqu", "jusque", "l", "la", "là", "laquelle", "le", "lequel", "les", "lesquelles", "lesquels", "leur", "leurs", "lorsque", "lui", "ma", "mais", "malgré", "me", "même", "mêmes", "merci", "mes", "mien", "mienne", "miennes", "miens", "moi", "moins", "mon", "moyennant", "n", "ne", "néanmoins", "ni", "non", "nos", "notre", "nôtre", "nôtres", "nous", "ô", "on", "ont", "ou", "où", "outre", "par", "parmi", "partant", "pas", "passé", "pendant", "plein", "plus", "plusieurs", "pour", "pourquoi", "près", "proche", "puisque", "qu", "quand", "que", "quel", "quelle", "quelles", "quels", "qui", "quoi", "quoique", "revoici", "revoilà", "s", "sa", "sauf", "se", "selon", "seront", "ses", "si", "sien", "sienne", "siennes", "siens", "sinon", "soi", "soit", "son", "sont", "sous", "suivant", "sur", "ta", "te", "tes", "tien", "tienne", "tiennes", "tiens", "toi", "ton", "tous", "tout", "toute", "toutes", "tu", "un", "une", "va", "voici", "voilà", "vos", "votre", "vôtre", "vôtres", "vous", "vu", "y"]
},
"french_stemmer": {
"type": "stemmer",
"language": "light_french"
},
"synonym": {
"type":"synonym",
"synonyms": [
"cie, compagnie",
"mme, madame, mam",
"mr, monsieur, msieur"
]
}
},
"analyzer": {
"french": {
"tokenizer":"standard",
"filter": [
"french_elision",
"lowercase",
"french_stop",
"french_stemmer",
"synonym"
]
}
}
}
}
}
}'
Depuis la version 1.5, le type multi-field est supprimé au profit d'un paramètre field.
# < 1.5
"title": {
"type": "multi_field",
"fields": {
"title": { "type": "string" },
"raw": { "type": "string", "index": "not_analyzed" }
}
}
# >= 1.5
"title": {
"type": "string",
"fields": {
"raw": { "type": "string", "index": "not_analyzed" }
}
}